package com.cyclingAssistant.route;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Random;

import javax.xml.parsers.SAXParserFactory;

import org.osmdroid.tileprovider.util.CloudmadeUtil;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.PathOverlay;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Toast;

public class DrawRoute extends PathOverlay {
	String CMurl;
	Boolean isBike = true;
	Boolean isRoundTrip = false;
	Context context;
	GeoPoint randomPoint;
	GeoPoint endPoint;

	public DrawRoute(int color, Context ctx, Boolean bike, Boolean round) {
		super(color, ctx);
		context = ctx;
		getPaint().setStrokeWidth(5f);
		CloudmadeUtil.retrieveCloudmadeKey(ctx);
		isBike = bike;
		isRoundTrip = round;
		CMurl = "http://routes.cloudmade.com/"
				+ CloudmadeUtil.getCloudmadeKey() + "/api/0.3/";
		Log.i("url", CMurl);
	}

	double endLat, endLng;

	public GeoPoint getRandomPoint() {
		return randomPoint;

	}
	
	public GeoPoint getEndPoint() {
		return endPoint;

	}

	// @Override
	// public boolean onSingleTapConfirmed(final MotionEvent e,
	// final MapView mapView) {
	// if (e.getAction()==MotionEvent.ACTION_DOWN) {
	// AlertDialog.Builder builder = new Builder(context);
	// // builder.setCancelable(false);
	// builder.setTitle("Nothing");
	// builder.setPositiveButton("Save", new OnClickListener() {
	//
	// @Override
	// public void onClick(DialogInterface dialog, int which) {
	// // TODO Auto-generated method stub
	// }
	// });
	// builder.show();
	// return true;
	// }
	// return false;
	// }

	public void showDirectionsToPredefinedLocation(double startLat,
			double startLng, boolean shortest, String lang, boolean metric)
			throws Exception {
		showDirections(startLat, startLng, endLat, endLng, shortest, lang,
				metric);
	}

	/**
	 * Request directions from a point to another point. Line is drawn
	 * automatically in the draw method, need to just request directions and
	 * parse the XML into the List of Point's.
	 * 
	 * @param startLat
	 *            Latitude of starting point
	 * @param startLng
	 *            Longitude of starting point
	 * @param endLat
	 *            Latitude of ending point
	 * @param endLng
	 *            Longitude of ending point
	 * @param shortest
	 *            Whether select shortest or fastest route
	 * @param lang
	 *            2-char ISO code of the language of directions
	 * @param metric
	 *            Whether use metric or imperial system
	 * @throws Exception
	 */
	public void showDirections(double startLat, double startLng, double endLat,
			double endLng, boolean shortest, String lang, boolean metric)
			throws Exception {
		/*
		 * Query up the routing service to figure out the turn points
		 * documentation for cloudmade routing service
		 * http://developers.cloudmade.com/wiki/routing-http-api/Documentation
		 */
		// add PARAMS to the URL
		// start_point,[transit_point1,...,transit_pointN],end_point/route_type[/route_type_modifier].output_format[?lang=(Two
		// letter ISO 3166-1 code)][&units=(km|miles)]
		CMurl += startLat + "," + startLng + "," + endLat + "," + endLng;
		// *****************************
		// ,[a.x, a,y], put middle points along the
		// road to at least give some different roads
		// *************
		if (isBike)
			CMurl += "/bicycle" + ".gpx?";
		else {
			CMurl += "/car" + ".gpx?";
		}
		if(isRoundTrip)
			CMurl = "http://184.72.53.173/roundTrip.gpx";
		Log.v("url, again", CMurl);
		// CMurl = "http://184.72.53.173/route.gpx";
		// fetch directions and parse returned XML
		String directionsXML = getContent(CMurl, null, "UTF8");
		// parse XML
		TurnPointsParser parser = new TurnPointsParser();
		XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser()
				.getXMLReader();
		xmlReader.setContentHandler(parser);
		if (!"".equals(directionsXML)) {
			xmlReader.parse(new InputSource(new StringReader(directionsXML)));
		}
	}

	public class TurnPointsParser extends DefaultHandler {

		public static final String ROOT_ELEMENT = "wpt";
		ArrayList<Point> tempPoints = new ArrayList<Point>();

		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes atts) throws SAXException {
			if (qName.equals(ROOT_ELEMENT)) {
				try {
					int late6 = degreesToMicrodegrees(Double.parseDouble(atts
							.getValue("lat")));
					int lnge6 = degreesToMicrodegrees(Double.parseDouble(atts
							.getValue("lon")));
					tempPoints.add(new Point(late6, lnge6));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		@Override
		public void endDocument() {
			setPoints(tempPoints);
		}
	}

	void setPoints(ArrayList<Point> points) {
		clearPath();
		for (Point p : points) {
			addPoint(p.x, p.y); // the core part: add points onto the path, then
								// the path is drawed automatically
			// Log.v("points", p.x+", "+p.y);
		}
		randomPoint = new GeoPoint(points.get(70).x, points.get(70).y);
		endPoint = new GeoPoint(points.get(points.size()-1).x, points.get(points.size()-1).y);
	}

	/**
	 * Fetch the content of service at the given URL with provided parameters.
	 * Also transcode the input into UTF-8 according to specified charset used
	 * by the service.
	 * 
	 * @param serviceUrl
	 * @param requestParams
	 * @param serviceCharset
	 * @return String with fetched content
	 * @throws Exception
	 */
	public static String getContent(String serviceUrl, String requestParams,
			String serviceCharset) throws Exception {
		URL service = new URL(serviceUrl);
		URLConnection serviceConnection = service.openConnection();
		serviceConnection.setDoOutput(true);
		// write request to the connection
		OutputStreamWriter request = new OutputStreamWriter(
				serviceConnection.getOutputStream());
		if (requestParams != null) {
			request.write(requestParams);
		}
		request.flush();
		// read returned output
		BufferedReader in = new BufferedReader(new InputStreamReader(
				serviceConnection.getInputStream(), serviceCharset));
		String inputLine;
		String returnedContent = "";
		while ((inputLine = in.readLine()) != null) {
			returnedContent += inputLine;
		}
		in.close();
		request.close();
		return returnedContent;
	}

	//
	// public static String getContent(String path) throws Exception {
	// String content = "";
	// String line = "";
	// File file = new File(path);
	// if (!file.exists()) {
	// Log.v("file", "not exist!");
	// }
	// BufferedReader reader = new BufferedReader(new FileReader(file));
	// while ((line = reader.readLine()) != null) {
	// content += line;
	// }
	// reader.close();
	// Log.v("content", content);
	// return content;
	// }

	public static final double MICRODEGREES_COEFF = 1E6;

	public static int degreesToMicrodegrees(double degrees) {
		return (int) (degrees * MICRODEGREES_COEFF);
	}

	public static double microdegreesToDegrees(int microdegrees) {
		return (double) microdegrees / (double) MICRODEGREES_COEFF;
	}

	public void setEndLat(double endLat) {
		this.endLat = endLat;
	}

	public void setEndLng(double endLng) {
		this.endLng = endLng;
	}

}
